// client.go
//
// 长连接客户端：
//   - 与服务器建立一次 TCP 连接
//   - 连续发送多条业务消息
//   - 后台 goroutine 持续读取服务器响应
//   - 使用定时器周期性发送心跳包
package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"os"
	"time"
)

const (
	serverAddr        = "127.0.0.1:901"  // 目标服务器地址
	heartbeatInterval = 10 * time.Second // 心跳发送周期
)

func main() {
	// 1. 建立 TCP 连接。可以使用 net.DialTimeout 指定拨号超时，本例使用默认配置。
	conn, err := net.Dial("tcp", serverAddr)
	if err != nil {
		log.Fatalf("dial error: %v", err)
	}
	defer conn.Close()

	log.Printf("已连接服务器 remote=%s local=%s",
		conn.RemoteAddr(), conn.LocalAddr())

	// 2. 启动 goroutine 持续读取服务器返回的数据。
	go func() {
		reader := bufio.NewScanner(conn)
		for reader.Scan() {
			log.Printf("收到服务器：%s", reader.Text())
		}
		if err := reader.Err(); err != nil {
			log.Printf("读取错误：%v", err)
		} else {
			log.Println("服务器关闭连接，客户端读循环结束")
		}
		os.Exit(0) // 服务器断开后退出程序
	}()

	// 3. 模拟业务侧发送多条消息，每条消息之间间隔 2 秒。
	businessPayloads := []string{
		"login user=alice token=123456",
		"publish room=42 body=HelloLongConn",
		"query order_id=2025001 status",
	}
	for _, payload := range businessPayloads {
		if _, err := fmt.Fprintf(conn, "%s\n", payload); err != nil {
			log.Fatalf("业务写失败: %v", err)
		}
		time.Sleep(2 * time.Second)
	}

	// 4. 使用 ticker 周期性发送心跳包，防止连接在空闲时被服务器超时关闭。
	ticker := time.NewTicker(heartbeatInterval)
	defer ticker.Stop()

	for range ticker.C {
		if _, err := fmt.Fprintf(conn, "PING\n"); err != nil {
			log.Fatalf("心跳发送失败: %v", err)
		}
		log.Println("发送心跳 PING")
	}
}
